const Scope = require("./scope");
const walk = require("./walk");
/*
 *root  _scope全局作用域
 *function _scope 函数作用域
 *_defines 局部变量定义
 *_dependsOn 变量依赖外部模块
 */
function analyze(ast) {
  //创建全局作用域
  let scope = new Scope();
  ast.body.forEach((statement) => {
    function addToScope(declaration) {
      let name = declaration.id.name;
      scope.add(name);
      if (!scope.parent) {
        statement._defines[name] = true;
      }
    }
    Object.defineProperties(statement, {
      _module: { value: module },
      _defines: { value: {} },
      _dependsOn: { value: {} },
      // _included: { value: false, writable: true }, //此语句是已经包含到输出语句里了
    });

    walk(statement, {
      enter(node) {
        let newScope;
        if (node == null || node.length == 0) return;
        switch (node.type) {
          case "FunctionDeclaration":
            addToScope(node);
            const params = node.params.map((v) => v.name);
            newScope = new Scope({
              parent: scope,
              params,
            });
            break;
          case "VariableDeclaration":
            node.declarations.forEach(addToScope);
            break;
          default:
            break;
        }
        if (newScope) {
          Object.defineProperties(node, {
            _scope: { value: newScope },
          });
          scope = newScope;
        }
      },
      leave(node) {
        if (node._scope) {
          // 如果此节点离开退回父作用域
          scope = scope.parent;
        }
      },
    });
  });
  ast._scope = scope;
  // 找出哪些变量需要外依赖
  ast.body.forEach((statement) => {
    walk(statement, {
      enter(node) {
        // if (node._scope) {
        //   scope = node._scope;
        // }
        if (node.type == "Identifier") {
          statement._dependsOn[node.name] = true;
        }
      },
      leave(node) {
        if (node._scope) scope = scope.parent;
      },
    });
  });
}

module.exports = analyze;
